package nuonuo.com.view.customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Scroller;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import nuonuo.com.view.R;

/**
 * Created by chenjun on 2017/3/4.
 */

public class MyHorizantalScrollerView extends ViewGroup {
    private Scroller mScroller;
    private Context mContext;
    private int mInterceptX, mInterceptY;
    private VelocityTracker mTracker;
    private int mLastX, mLastY;
    private int mHideViewsNum;
    private boolean isFirstMeasure = true;
    private int mShowWidth;
    private int mHideWidth;
    public static final int SHOW = 1;
    public static final int HIDE = 2;
    private int MODE = HIDE;
    private int mTouchTempX;
    private int mTouchTempY;
    private float xVelocity;
    private List<OnHideItemClickListener> list;
    private ViewConfiguration mConfiguration;

    public MyHorizantalScrollerView(Context context) {
        this(context, null);
    }

    public MyHorizantalScrollerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyHorizantalScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        list = new ArrayList<>();
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyHorizantalScrollerView);
        mHideViewsNum = a.getInt(R.styleable.MyHorizantalScrollerView_number, 0);
        mScroller = new Scroller(context);
        mTracker = VelocityTracker.obtain();
        mConfiguration = ViewConfiguration.get(context);
        a.recycle();
    }

    public void smoothScrollTo(int destX, int destY) {
        int startX = getScrollX();
        int deltaX = destX - startX;
        mScroller.startScroll(startX, 0, deltaX, 0, 500);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        List<View> list = new ArrayList<>();
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (isFirstMeasure) {
            mShowWidth = getMeasuredWidth();
            isFirstMeasure = true;
        }
        if (mShowWidth == 0) {
            mShowWidth = getMeasuredWidth();
        } else if (mShowWidth > getMeasuredWidth()) {
            mShowWidth = getMeasuredWidth();
        }
        int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec);
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(mShowWidth, widthMeasureMode);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int height = 0;
        int hideWidth = 0;
        int childCount = getChildCount();
        switch (heightMode) {
            case MeasureSpec.UNSPECIFIED:
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
                measureChildren(widthMeasureSpec, heightMeasureSpec);
            case MeasureSpec.AT_MOST:
                for (int i = 0; i < childCount; i++) {
                    View child = getChildAt(i);
                    LayoutParams params = (LayoutParams) child.getLayoutParams();
                    if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
                        list.add(child);
                    } else if (params.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                        height = Math.max(height, child.getMeasuredHeight() + params.bottomMargin + params.topMargin);
                    } else if (params.height > 0) {
                        height = Math.max(height, child.getMeasuredHeight() + params.bottomMargin + params.topMargin);
                    }
                    if (i >= childCount - mHideViewsNum) {
                        hideWidth += child.getMeasuredWidth() + params.leftMargin + params.rightMargin;
                    }
                }
                mHideWidth = hideWidth;
                if (list.size() != 0) {
                    int realHeightSpec;
                    for (int i = 0; i < list.size(); i++) {
                        View child = list.get(i);
                        LayoutParams params = (LayoutParams) child.getLayoutParams();
                        if (child.getMeasuredHeight() < (height - params.bottomMargin - params.topMargin)) {
                            realHeightSpec = MeasureSpec.makeMeasureSpec(height - params.bottomMargin - params.topMargin, MeasureSpec.EXACTLY);
                            measureChild(child, widthMeasureSpec, realHeightSpec);
                        }
                    }
                }
                break;
            case MeasureSpec.EXACTLY:
                MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();
                height = getMeasuredHeight() + params.topMargin + params.bottomMargin;
                break;
        }
        setMeasuredDimension(mShowWidth, height);
    }

    private int mInterceptTempX;
    private int mInterceptTempY;
    private boolean intercept = false;
    private boolean hasIntercept = false;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        intercept = false;
        mInterceptTempX = (int) ev.getX();
        mInterceptTempY = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercept = false;
                if (!mScroller.isFinished()) {
                    intercept = true;
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.sqrt(3) * Math.abs(mInterceptTempX - mInterceptX) > Math.abs(mInterceptTempY - mInterceptY)) {
                    intercept = true;
                    hasIntercept = true;
                } else {
                    if (!hasIntercept)
                        intercept = false;
                    else
                        intercept = true;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercept = false;
                break;
            default:
                break;
        }
        mInterceptX = mInterceptTempX;
        mInterceptY = mInterceptTempY;
        mLastX = mInterceptTempX;
        mLastY = mInterceptTempY;
        return intercept;
    }

    private boolean hasMoved;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mTouchTempX = (int) event.getX();
        mTouchTempY = (int) event.getY();
        mTracker.addMovement(event);
        xVelocity = 0;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                hasMoved = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(mLastX - mTouchTempX) > 5 || hasMoved){
                    hasMoved = true;
                    scrollBy(mLastX - mTouchTempX, 0);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (hasMoved) {
                    mTracker.computeCurrentVelocity(1000);
                    xVelocity = mTracker.getXVelocity();
                    Logger.i("ACTION_UP");
                    if (Math.abs(xVelocity) >= 50) {
                        if (xVelocity > 0) {
                            hideViews();
                        } else {
                            showViews();
                        }
                    } else {
                        int scrollX = getScrollX();
                        Logger.i(scrollX + "");
                        Logger.i(mHideWidth + "");
                        if ((scrollX + mHideWidth / 2) >= mHideWidth) {
                            showViews();
                        } else {
                            hideViews();
                        }
                    }
                }else {
                    performClick();
                }
        }
        mLastX = mTouchTempX;
        mLastY = mTouchTempY;
        mTracker.clear();
        return true;
    }

    public void hideViews() {
        smoothScrollTo(0, 0);
        MODE = HIDE;
    }

    public void showViews() {
        smoothScrollTo(mHideWidth, 0);
        MODE = SHOW;
    }

    public int getMODE() {
        return MODE;
    }

    public void setMODE(int MODE) {
        this.MODE = MODE;
    }

    public static class LayoutParams extends MarginLayoutParams {

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        } else if (lp instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) lp);
        } else {
            return new LayoutParams(lp);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mTracker.recycle();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int currentWidth = 0;
        int mHideWidth = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            LayoutParams params = (LayoutParams) child.getLayoutParams();
            child.layout(params.leftMargin + currentWidth, params.topMargin, params.leftMargin + childWidth + currentWidth, params.topMargin + childHeight);
            currentWidth += (params.leftMargin + childWidth + params.rightMargin);
            if (i >= childCount - mHideViewsNum) {
                child.layout(mShowWidth + params.leftMargin + mHideWidth, params.topMargin, mShowWidth + params.leftMargin + mHideWidth + childWidth, params.topMargin + childHeight);
                mHideWidth += child.getMeasuredWidth() + params.leftMargin + params.rightMargin;
            }
        }
    }
}
